﻿@* Generator: Template
    GeneratePrettyNames : true *@
@functions{
    public Compile.Template.Startup.RouterModel Model { get; set; }
}
﻿//======================================================================
//
//        Copyright : Zhengzhou Strawberry Computer Technology Co.,LTD.
//        All rights reserved
//        
//        Application:NFinal MVC framework
//        Filename :Router.cs
//        Description :路由类
//
//        created by Lucas at  2015-10-15`
//     
//        WebSite:http://www.nfinal.com
//
//======================================================================
using System;
using System.Collections.Generic;
#if (!MicrosoftOwin && !NFinalOwin)
using System.Web;
#endif
using System.Threading;
using System.Globalization;
using System.Text.RegularExpressions;
using NFinal;

namespace @{@Model.project}
{
#if (!MicrosoftOwin && !NFinalOwin)
    public static class Router
    {
        public static string GetString(string val, string de)
        {
            return string.IsNullOrEmpty(val) ? de : val;
        }
        public static string UCFirst(string val)
        {
            CultureInfo cultureInfo = Thread.CurrentThread.CurrentCulture;
            return cultureInfo.TextInfo.ToTitleCase(val);
        }
		 private static void Callback(IAsyncResult result)
        {
            //结束异步写入
            System.IO.FileStream stream = (System.IO.FileStream)result.AsyncState;
            stream.EndWrite(result);
            stream.Dispose();
        }
		//设置浏览器缓存
        public static void SetBrowerCache(HttpContext context,int optimizing,int seconds)
        {
            //浏览器缓存
            if ((optimizing & (int)NFinal.Optimizing.Cache_Brower_Cached) != 0)
            {
                context.Response.Cache.SetCacheability(HttpCacheability.Public);
                //NotModify
                if ((optimizing & (int)NFinal.Optimizing.Cache_Browse_NotModify) != 0)
                {
                    context.Response.Cache.SetLastModifiedFromFileDependencies();
                }
                //Expires
                else if ((optimizing & (int)NFinal.Optimizing.Cache_Browser_Expires) != 0)
                {
                    context.Response.Cache.SetExpires(DateTime.Now.AddSeconds(seconds));
                }
                //NoExpires
                else if ((optimizing & (int)NFinal.Optimizing.Cache_Browser_NoExpires) != 0)
                {
                }
            }
            else
            {
                //不进行缓存
                context.Response.Cache.SetNoStore();
            }
        }
        //设置服务器缓存
        public static void SetServerCacheAndOutPut(HttpContext context, string url, string query, byte[] buffer, int optimizing, int seconds)
        {
            //服务器缓存
            if ((optimizing & (int)NFinal.Optimizing.Cache_Server_Cached) != 0)
            {
                //FileDependency
                if ((optimizing & (int)NFinal.Optimizing.Cache_Server_FileDependency) != 0)
                {
					string fileName=null;
					if(url.EndsWith("/"))
					{
						fileName = NFinal.Utility.MapPath(url+"Index.html");
					}
                    else
					{
						fileName = NFinal.Utility.MapPath(url);
					}
					if ((optimizing & (int)NFinal.Optimizing.CompressZip) != 0)
                    {
                        fileName = fileName + ".zip";
                    }
                    else if ((optimizing & (int)NFinal.Optimizing.CompressDeflate) != 0)
                    {
                        fileName = fileName + ".deflate";
                    }
                    //将HTML写入静态文件
                    if (!System.IO.File.Exists(fileName))
                    {
                        string dir = System.IO.Path.GetDirectoryName(fileName);
                        if (!System.IO.Directory.Exists(dir))
                        {
                            System.IO.Directory.CreateDirectory(dir);
                        }
                        System.IO.FileStream file = new System.IO.FileStream(fileName, System.IO.FileMode.Create, System.IO.FileAccess.Write, System.IO.FileShare.ReadWrite, 1024, true);
                        file.BeginWrite(buffer, 0, buffer.Length, new AsyncCallback(Callback), file);
                    }
					if (seconds > 0)
                    {
						//将HTML插入新的缓存
						System.Web.Caching.CacheDependency dep = new System.Web.Caching.CacheDependency(fileName);
						HttpRuntime.Cache.Insert(url, buffer, dep, System.Web.Caching.Cache.NoAbsoluteExpiration, System.Web.Caching.Cache.NoSlidingExpiration);
					}
                }
                //AbsoluteExpiration
                else if ((optimizing & (int)NFinal.Optimizing.Cache_Server_AbsoluteExpiration) != 0)
                {
                    HttpRuntime.Cache.Insert(url+query, buffer, null, DateTime.Now.AddSeconds(seconds), System.Web.Caching.Cache.NoSlidingExpiration);
                }
                //SlidingExpiration
                else if ((optimizing & (int)NFinal.Optimizing.Cache_Server_SlidingExpiration) != 0)
                {
                    HttpRuntime.Cache.Insert(url+query, buffer, null, System.Web.Caching.Cache.NoAbsoluteExpiration, new TimeSpan(0, 0, seconds));
                }
            }
            //直接输出
            context.Response.OutputStream.Write(buffer, 0, buffer.Length);
            context.Response.OutputStream.Dispose();
        }
        //写入缓存
        public static bool WriteCache(HttpContext context,string url,int optimizing)
        {
            //服务器缓存
            if ((optimizing & (int)NFinal.Optimizing.Cache_Server_Cached) != 0)
            {
                object cache = HttpRuntime.Cache.Get(url);
                //如果缓存存在则直接输出.
                if (cache != null)
                {
                    if ((optimizing & (int)NFinal.Optimizing.Comresssed) != 0)
                    {
                        if ((optimizing & (int)NFinal.Optimizing.CompressZip) != 0)
                        {
                            context.Response.AppendHeader("Content-encoding", "gzip");
                        }
                        else if ((optimizing & (int)NFinal.Optimizing.CompressDeflate) != 0)
                        {
                            context.Response.AppendHeader("Content-encoding", "deflate");
                        }
                    }
                    byte[] buffer= (byte[])cache;
                    context.Response.OutputStream.Write(buffer, 0, buffer.Length);
                    context.Response.OutputStream.Dispose();
                    return true;
                }
            }
            return false;
        }
        /// <summary>
        /// 计算actionUrl
        /// </summary>
        /// <param name="requestedPath"></param>
        /// <returns></returns>
        private static string GetActionUrl(string requestedPath)
        {
            int position = requestedPath.LastIndexOf('.');
            string actionUrl = "";
            if (position > 0)
            {
				int pointer = 0;
                bool hasGet = int.TryParse(requestedPath.Substring(position - 2, 2), out pointer);
                if (hasGet)
                {
                    actionUrl = requestedPath.Substring(0, pointer + 1);
                }
                else
                {
                    actionUrl = requestedPath;
                }
            }
            return actionUrl;
        }
        public static void Run(HttpContext context, string requestedPath)
        {
            //取出action标识
            int find = 0;
            string f = requestedPath.Substring(requestedPath.Length - 8, 5);
            int.TryParse(requestedPath.Substring(requestedPath.Length - 8, 5), out find);
            //去掉00000.htm后缀,还原requestPath
            requestedPath = requestedPath.Substring(0, requestedPath.Length - 8);
            string[] hostName = context.Request.Url.Host.ToString().Split('.');
            string subdomain = hostName.Length == 3 ? hostName[0] : "www";
            IDictionary<string,StringContainer> get = new Dictionary<string,StringContainer>();
			//提取MethodType
            NFinal.MethodType methodType = NFinal.MethodType.NONE;
            switch (context.Request.HttpMethod)
            {
                case "POST": methodType = NFinal.MethodType.POST; break;
                case "GET": methodType = NFinal.MethodType.GET; break;
                case "DELETE": methodType = NFinal.MethodType.DELETE; break;
                case "PUT": methodType = NFinal.MethodType.PUT; break;
                case "AJAX": methodType = NFinal.MethodType.AJAX; break;
                default: methodType = NFinal.MethodType.NONE; break;
            }
            //提取内容类型
			Dictionary<string,NFinal.HttpFile> files = null;
			if (methodType == NFinal.MethodType.POST)
			{
				NFinal.ContentType contentType = NFinal.ContentType.NONE;
				switch (context.Request.ContentType.Split(';')[0])
				{
					case "multipart/form-data":contentType = NFinal.ContentType.Multipart_form_data; break;
                    case "text/json":
					case "application/json":contentType = NFinal.ContentType.Application_json; break;
					case "application/x-www-form-urlencoded":contentType = NFinal.ContentType.Application_x_www_form_urlencoded; break;
                    case "application/xml":
                    case "text/xml":contentType = NFinal.ContentType.Text_xml; break;
					case "application/octet-stream":contentType = NFinal.ContentType.Application_octet_stream;break;
					default:contentType = NFinal.ContentType.NONE; break;
				}
				//提取form参数
				if (context.Request.InputStream!=System.IO.Stream.Null)
				{
					if (contentType == NFinal.ContentType.Application_x_www_form_urlencoded)
					{
						System.IO.StreamReader sr = new System.IO.StreamReader(context.Request.InputStream);
						string body = sr.ReadToEnd();
						sr.Dispose();
						if (!string.IsNullOrEmpty(body))
						{
							string[] formArray = body.Split('&', '=');
							if (formArray.Length > 1 && (formArray.Length & 1) == 0)
							{
								for (int i = 0; i < formArray.Length; i += 2)
								{
									get.AddValue(formArray[i], formArray[i + 1]);
								}
							}
						}
					}
					else if (contentType == NFinal.ContentType.Text_xml)
					{
						System.IO.StreamReader sr = new System.IO.StreamReader(context.Request.InputStream);
						string body = sr.ReadToEnd();
						sr.Dispose();
						if (!string.IsNullOrEmpty(body))
						{
							System.Xml.XmlDocument doc = new System.Xml.XmlDocument();
							doc.LoadXml(body);
							foreach (System.Xml.XmlElement xmlNode in doc.DocumentElement.ChildNodes)
							{
								get.AddValue(xmlNode.Name, xmlNode.Value);
							}
						}
					}
					else if (contentType == NFinal.ContentType.Application_json)
					{
						System.IO.StreamReader sr = new System.IO.StreamReader(context.Request.InputStream);
                        string body = sr.ReadToEnd();
                        sr.Dispose();
                        IDictionary<string,object> data= SimpleJson.DeserializeObject <IDictionary<string, object>>(body);
                        foreach (var ele in data)
                        {
                            get.AddValue(ele.Key, ele.Value.ToString());
                        }
					}
					else if (contentType == NFinal.ContentType.Multipart_form_data)
					{
						//multipart/form-data
						string boundary =NFinal.HttpMultipart.boundaryReg.Match(context.Request.ContentType).Value;
						files = new Dictionary<string, NFinal.HttpFile>();
						var multipart = new NFinal.HttpMultipart(context.Request.InputStream, boundary);
						foreach (var httpMultipartBoundary in multipart.GetBoundaries())
						{
							if (string.IsNullOrEmpty(httpMultipartBoundary.Filename))
							{
								string name = httpMultipartBoundary.Name;
								if (!string.IsNullOrEmpty(name))
								{
									string value = new System.IO.StreamReader(httpMultipartBoundary.Value).ReadToEnd();
									get.AddValue(name, value);
								}
							}
							else
							{
								files.Add(httpMultipartBoundary.Name,new NFinal.HttpFile(httpMultipartBoundary));
							}
						}
					}
				}
			}
			//提取URL?后的参数
			if (context.Request.QueryString.Count > 0)
            {
                for (int i = 0; i < context.Request.QueryString.Count; i++)
                {
                    get.AddValue(context.Request.QueryString.Keys[i], context.Request.QueryString[i]);
                }
            }
            //获取actionUrl,用于获取参数
            string actionUrl = GetActionUrl(requestedPath);
            switch (find)
            {
				@{int i=1;int j=1;
				foreach(var fileData in Model.controllerFileDataList){
				var config=fileData.config;
                foreach(var classData in fileData.ClassDataList){
				foreach(var method in classData.MethodDataList){
					if(method.isPublic){
					@:case @i:
					@:{
						@:context.Response.ContentType = "@{@method.contentType}";
						if(!method.urlParser.hasNoParamsInUrl){
							@:Regex regParameters = new Regex("@{@method.urlParser.parameterRegex}");
							@:Match matParameters = regParameters.Match(requestedPath);
							j=1;
							foreach(var parameterData in method.parameterDataList){
							if(parameterData.isUrlParameter){
							@:if (get["@{@parameterData.name}"] == null)
							@:{
								@:get.Add("@{@parameterData.name}", matParameters.Groups[@j].Value);
							@:}
							@:else
							@:{
								@:get["@{@parameterData.name}"] = matParameters.Groups[@j].Value;
							@:}
							j++;
							}
							}
						}
						@:@method.verifyCode
						if(method.optimizing==0){
						@:@{@fileData.appName}.Web.@{@config.defaultStyle}@{@classData.relativeDotName}.@{@method.name}Action control= new @{@fileData.appName}.Web.@{@config.defaultStyle}@{@classData.relativeDotName}.@{@method.name}Action(context);
						foreach(var parameterData in method.parameterDataList){
							@parameterData.getParamterCode
						}
						@:control._methodType = methodType;
						@:control._context = context;
						@:control._subdomain = subdomain;
						@:control._url=requestedPath;
						@:control._get = get;
						@:control._app="/@{@fileData.appName}";
						@:control.Before();
						@:control.@{@method.name}(@{@method.parameterNames});
						@:control.After();
						@:control.Close();
						@:context.Response.End();
						}else{
						//优化选项
                        @:int optimizing = @{@method.optimizing};
                        @:int minutes = @{@method.minutes};
                        @:string url = requestedPath;
                        @:string query = context.Request.QueryString.ToString();
                        @:bool compress = (optimizing & (int)NFinal.Optimizing.Comresssed)!=0;
                        //设置浏览器缓存
                        @:SetBrowerCache(context, optimizing, seconds);
                        //是否启用了服务器缓存
                        @:bool serverCahce = (optimizing & (int)NFinal.Optimizing.Cache_Server_Cached) != 0;
                        @:bool hasCache = false;
                        //服务器缓存
                        @:if (serverCahce)
                        @:{
                            //如果是文件缓存，不加query
							@:if ((optimizing & (int)NFinal.Optimizing.Cache_Server_FileDependency) != 0)
							@:{
								@:hasCache=WriteCache(context,url,optimizing);
							@:}
                            @:else
							@:{
								@:hasCache=WriteCache(context,url+query,optimizing);
							@:}
                        @:}
                        //如果没有缓存
                        @:if (!hasCache)
                        @:{
                            @:System.IO.MemoryStream htmlStream = new System.IO.MemoryStream();
                                    
                            @:@{@fileData.appName}.Web.@{@config.defaultStyle}@{@classData.relativeDotName}.@{@method.name}Action control = null;
                            @:System.IO.Stream stream = null;
                            @:System.IO.StreamWriter sw = null;
                            //如果有压缩或缓存
                            @:if (compress || serverCahce)
                            @:{
                                @:if ((optimizing & (int)NFinal.Optimizing.Comresssed) != 0)
                                @:{
                                    @:if ((optimizing & (int)NFinal.Optimizing.CompressZip) != 0)
                                    @:{
                                        @:stream = new System.IO.Compression.GZipStream(htmlStream, System.IO.Compression.CompressionMode.Compress, true);
                                        @:context.Response.AppendHeader("Content-Encoding", "gzip");
                                    @:}
                                    @:else if ((optimizing & (int)NFinal.Optimizing.CompressDeflate) != 0)
                                    @:{
                                        @:stream = new System.IO.Compression.DeflateStream(htmlStream, System.IO.Compression.CompressionMode.Compress, true);
                                        @:context.Response.AppendHeader("Content-Encoding", "deflate");
                                    @:}
                                    @:sw = new System.IO.StreamWriter(stream);
                                @:}
                                @:else
                                @:{
                                    @:sw = new System.IO.StreamWriter(htmlStream);
                                @:}
                                @:control = new @{@fileData.appName}.Web.@{@config.defaultStyle}@{@classData.relativeDotName}.@{@method.name}Action(sw);
                            @:}
                            @:else
                            @:{
                                @:control = new @{@fileData.appName}.Web.@{@config.defaultStyle}@{@classData.relativeDotName}.@{@method.name}Action(context);
                            @:}
							foreach(var parameterData in method.parameterDataList){
								@parameterData.getParamterCode
							}
                            @:control._context = context;
                            @:control._subdomain = subdomain;
                            @:control._url = requestedPath;
                            @:control._get = get;
							@:control._files = files;
                            @:control._app="/@{@fileData.appName}";
                            @:control.Before();
                            @:control.@{@method.name}(@{@method.parameterNames});
                            @:control.After();
                            @:control.Close();
                            @:byte[] buffer = htmlStream.ToArray();
							@:htmlStream.Dispose();
                            //如果有压缩或缓存
                            @:if (compress || serverCahce)
                            @:{
                                @:SetServerCacheAndOutPut(context, url, query, buffer, optimizing, minutes);
                            @:}	
						@:}
						}
					@:}break;
					i++;
					}
				}
				}
				}
				}
                default: break;
            }
        }
    }
#endif
}